package Tier3;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.xml.bind.JAXBElement;

import Shared.Players;

//+----------------------------------------------------------------------+
//| (sous Linux)
//| Pour générer le WAR  de UserManager (créé dans Tier3/build)
//|     cd <workspace>/SIL6\ -\ Bataille/src/Tier3
//|     ./compile.sh
//|
//| Pour démarrer Glassfish
//|     cd <glassfish3>
//|     glassfish/bin/asadmin start-domain
//|
//| Pour déployer le WAR sur Glassfish
//|     localhost:<4848>
//|     > applications > deployer > importer le WAR > type : application web > ok
//|     > lancer
//|	> dans la popup recuperer l'url fournie (http) et modifier les variables 
//|	  GLASSFISH_HOST && GLASSFISH_PORT dans le fichier _Config si necessaire
//|
//+----------------------------------------------------------------------+  

@Path("/")
public class UserManager implements Serializable {
    private static final long serialVersionUID = 1L;
    private static final String bak_players = "/tmp/Players.bak";
    
    private static Players players;
    
    public UserManager() { 
	restorePlayers(); 
    }
    public void finalize() {
	savePlayers();
    }
    
    /**
     * Verifie dans la liste de joueurs si le joueur donné existe <br>
     * (combinaison nom + password, ou si password=null juste le nom)
     * @param name
     * @param password (/null)
     * @return le joueur s'il existe ou Player vide
     */
    @PUT
    @Path("checkAuth")
    @Consumes("text/plain")  
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public Shared.Player checkAuth(@QueryParam("name") String name, @QueryParam("password") String password) {
	for(Shared.Player p : players.liste) {
		
	    if(p.getName().contentEquals(name)) {
	    	if(password.isEmpty() || p.comparePwd(password)){
	    		System.out.println(" = user[/password] reconnu");
	    		return p;
		}
	    }
	}
	return new Shared.Player();
    }
    
    /**
     * Créé un nouvel utilisateur en BD et l'initialise (score, etc)
     * @param name
     * @param password
     * @return l'utilisateur ou Player vide s'il existe déjà
     */
    @PUT
    @Path("createPlayer")
    @Consumes("text/plain")  
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public Shared.Player createPlayer(@QueryParam("name") String name, @QueryParam("password") String password) {
	System.out.print("checkAuth param = " + name + " - " + password);
    	if(checkAuth(name, password).getName().isEmpty()) {
    	    
		Shared.Player player = new Shared.Player(name, password);
		players.liste.add(player);
		savePlayers();
		return player;
	}
	return new Shared.Player();
    }
    
    /**
     * liste les joueurs de la BD
     */
    @GET
    @Path("listerPlayers")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public Players listerJoueurs() {
	return players;
    }

    /**
     * addPlayer
     * @return faux si le joueur existe déjà (objet)
     */
    @PUT
    @Path("addPlayer")
    @Consumes(MediaType.APPLICATION_XML)
    @Produces("text/plain")
    public String addPlayer(JAXBElement<Shared.Player> p) {
	Shared.Player player = p.getValue();

	if (players.liste.contains(player)) {
	    return "false";
	}

	players.liste.add(player);
	savePlayers();
	return "true";
    }

  //+----------------------------------------------------------------------+
  //|
  //| PERSISTENCE DES DONNEES (méthodes internes à UserManager)
  //|
  //+----------------------------------------------------------------------+
    
    /**
     * Dump l'ensemble des joueurs (objets sérialisés) dans un fichier binaire
     */
    private void restorePlayers() {
	try {
	    FileInputStream fichier = new FileInputStream(bak_players);
	    ObjectInputStream in = new ObjectInputStream(fichier);
	    players = ((Players) in.readObject());
	} catch (Exception e) {
	    System.out.print("BD :: Pb de Restauration ou fichier non encore créé ("+ bak_players +")");
	    e.printStackTrace();
	    
	    players = new Players();
	}
    }
    /**
     * Sauvegarde l'ensemble des joueurs (serialisés) dans un fichier binaire
     */
    private void savePlayers() {
	try {
	    FileOutputStream f = new FileOutputStream(bak_players);
	    ObjectOutputStream out = new ObjectOutputStream(f);
	    out.writeObject(players);
	} catch (Exception e) {
	    System.out.print("BD :: Pb de Sauvegarde dans le fichier ("+ bak_players +")");
	    e.printStackTrace();
	}
    }

}